<?php defined('SYSPATH') or die('No direct script access.');

class Session_Database extends Session 
{
	protected $_db;

	public function id()
	{
		$cookie = Cookie::get('sess_id');
		if (empty($cookie))
		{
			$cookie = $this->_random(8);
			Cookie::set('sess_id', $cookie, $this->_lifetime);
		}

		return $cookie;
	}

	public function __construct($config = NULL, $id = NULL)
	{
		$name = !empty($config['driver']) ? $config['driver'] : 'default';
		$this->_db = Database::instance($name);
		parent::__construct($config, $id);
	}

	public function _read($id = NULL)
	{
		empty($id) && ($id = $this->id());
		$sql = "SELECT * FROM my_sessions WHERE sid = ?";
		$rtn = $this->_db->fetchRow($sql, $id);
		if (empty($rtn)) 
		{
			return NULL;
		}
		else
		{
			$rtn = (array)$rtn;
			$other = $rtn['other'];

			try
			{
				if ($this->_encrypted)
				{
					// Decrypt the data using the default key
					$other = Encrypt::instance($this->_encrypted)->decode($other);
				}
				else
				{
					// Decode the base64 encoded data
					$other = base64_decode($other);
				}

				// Unserialize the data
				$other = unserialize($other);
			}
			catch (Exception $e)
			{
				// Ignore all reading errors
			}
			unset($rtn['sid'], $rtn['ip1'], $rtn['ip2'], $rtn['ip3'], $rtn['ip4'], $rtn['other']);
			$rtn += $other;
			return $rtn;
		}
	}

	protected function _regenerate()
	{
		$cookie = $this->_random(8);
		Cookie::delete('sess_id');
		Cookie::set('sess_id', $cookie, $this->_lifetime);
		return $cookie;
	}

	protected function _write()
	{
		$id = $this->id();
		$ips = explode('.', Request::$client_ip);
		$logger_uid = empty($this->_data['uid']) ? 0 : intval($this->_data['uid']);
		$logger_user = empty($this->_data['username']) ? '' : intval($this->_data['username']);
		$lastactivity = empty($this->_data['last_active']) ? time() : $this->_data['last_active'];
		unset($this->_data['uid'], $this->_data['username'], $this->_data['last_active']);

		$sid = array('sid' => $id);
		$set = array('ip1' => $ips[0], 'ip2' => $ips[1], 'ip3' => $ips[2], 'ip4' => $ips[3], 'uid' => $logger_uid, 'username' => $logger_user, 'other' => $this->__toString(), 'lastactivity' => $lastactivity);

		$sql = "DELETE FROM my_sessions WHERE `lastactivity` < ?";
		$this->_db->query($sql, time()-$this->_lifetime);

		if (($affected = $this->_db->update('my_sessions', $set, $sid)) < 1)
		{
			$set = $sid+$set;
			$affected = $this->_db->insert('my_sessions', $set);
		}
		return $affected;
	}

	protected function _destroy()
	{
		$id = array('sid' => $this->id());
		return $this->_db->delete('my_sessions', $id);
	}

	private function _random($length, $numeric = 0)
	{
		PHP_VERSION < '4.2.0' ? mt_srand((double)microtime() * 1000000) : mt_srand();
		$seed = base_convert(md5(print_r($_SERVER, 1).microtime()), 16, $numeric ? 10 : 35);
		$seed = $numeric ? (str_replace('0', '', $seed).'012340567890') : ($seed.'zZ'.strtoupper($seed));
		$hash = '';
		$max = strlen($seed) - 1;
		for($i = 0; $i < $length; $i++) {
			$hash .= $seed[mt_rand(0, $max)];
		}
		return $hash;
	}
}